package app

import (
	"IEC104_Master/asdu"
	"IEC104_Master/cs104"
	"fmt"
	"log"
	"time"
)

func CreateNewMaster(host string, port int) {
	var err error
	option := cs104.NewOption()
	if err = option.AddRemoteServer("127.0.0.1:2404"); err != nil {
		panic(err)
	}

	mycli := &myMaster{}

	client := cs104.NewClient(mycli, option)

	client.SetOnConnectHandler(func(c *cs104.Client) {
		c.SendStartDt() // 发送startDt激活指令
		// 等待激活确认后发起总召唤
		go func() {
			//todo 启动一个线程发送召唤命令
			time.Sleep(2 * time.Second) // 等待2秒确保激活确认
			sendInterrogationCommand(c)
		}()

	})
	err = client.Start()
	if err != nil {
		panic(fmt.Errorf("Failed to connect. error:%v\n", err))
	}
}

type myMaster struct{}

func (myMaster) InterrogationHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}

func (myMaster) CounterInterrogationHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}
func (myMaster) ReadHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}

func (myMaster) TestCommandHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}

func (myMaster) ClockSyncHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}
func (myMaster) ResetProcessHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}
func (myMaster) DelayAcquisitionHandler(asdu.Connect, *asdu.ASDU) error {
	return nil
}
func (myMaster) ASDUHandler(c asdu.Connect, u *asdu.ASDU) error {
	// 根据不同的TypeID进行不同的解析
	switch u.Type {
	case asdu.M_SP_NA_1:
		// 1 解析单点信息[遥信数据]
		bitStringInfos := u.GetSinglePoint()
		yxMap := make(map[asdu.InfoObjAddr]bool)
		for _, info := range bitStringInfos {
			//fmt.Printf("InfoObjAddr: %d, Value: %v\n", info.Ioa, info.Value)
			yxMap[info.Ioa] = info.Value
		}
		log.Printf("遥信数据:%v\n", yxMap)
		break
	case asdu.M_ME_NC_1:
		// 13 解析单点浮点[遥测]
		bitStringInfos := u.GetMeasuredValueFloat()
		ycMap := make(map[asdu.InfoObjAddr]float32)
		for _, info := range bitStringInfos {
			//fmt.Printf("InfoObjAddr: %d, Value: %v\n", info.Ioa, info.Value)
			ycMap[info.Ioa] = info.Value
		}
		log.Printf("遥测数据:%v\n", ycMap)
	default:
		fmt.Printf("Unsupported TypeID: %d\n", u.Type)
	}
	return nil
}
func sendInterrogationCommand(c *cs104.Client) {
	// 构造总召唤的ASDU
	coa := asdu.CauseOfTransmission{
		Cause: asdu.Activation,
	}
	ca := asdu.GlobalCommonAddr
	ioa := asdu.InfoObjAddr(0)               // 信息对象地址
	qoi := asdu.QualifierOfInterrogation(20) // 召唤限定词

	// 创建ASDU
	asduPack := asdu.NewASDU(c.Params(), asdu.Identifier{
		asdu.C_IC_NA_1,
		asdu.VariableStruct{IsSequence: false, Number: 1},
		coa,
		0,
		ca,
	})

	// 设置信息对象地址和召唤限定词
	if err := asduPack.AppendInfoObjAddr(ioa); err != nil {
		fmt.Printf("Failed to append info object address: %v\n", err)
		return
	}
	asduPack.AppendBytes(byte(qoi))

	// 发送ASDU
	if err := c.Send(asduPack); err != nil {
		fmt.Printf("Failed to send interrogation command: %v\n", err)
		return
	}

	fmt.Println("Interrogation command sent successfully")
}
